home *** CD-ROM | disk | FTP | other *** search
/ CD ROM Paradise Collection 4 / CD ROM Paradise Collection 4 1995 Nov.iso / program / swagd_f.zip / DRIVES.SWG / 0096_Re: IDE HDD Parameters?.pas < prev    next >
Pascal/Delphi Source File  |  1995-02-28  |  10KB  |  320 lines

  1. {
  2.  
  3.  The code below identifies some of the IDE params. Actually, it identifies
  4.  most of what you'd ever need.
  5.  Theres only one catch. The main program checks the letter given on the
  6.  command line using a function:
  7.  DriveValid(Drive: Char; var Drv: Byte): Boolean; assembler;
  8.  This returns the numeric equivalent of the Drive character into Drv and
  9.  returns true/false if the Drive is Valid. The trick is the validity check
  10.  is done by DOS. Meaning that on my machine, my second drive, a HPFS drive
  11.  won't show up unless I stick something like Drive=3 (Second HDD) and
  12.  disable the DriveValid check. I hope this helps.
  13.  
  14. }
  15.  
  16. (*******************************************************************
  17.     idediag
  18.     shows characteristics of IDE hard disks.
  19.     Public Domain by Paolo Bevilacqua, Rome.
  20.     Rewritten from C to Turbo Pascal 7.0 by Ivan Peev, Sofia.
  21.     You can add more disk type to the idetypes[]
  22.     table, and distribuite freely.
  23. ********************************************************************)
  24.  
  25. const
  26. { read/write }
  27.    HDC_DATA    = $01F0;
  28.    HDC_ERROR   = $01F1;
  29.    HDC_SECCOU  = $01F2;
  30.    HDC_SECNUM  = $01F3;
  31.    HDC_CYLLOW  = $01F4;
  32.    HDC_CYLHIGH = $01F5;
  33.    HDC_SDH     = $01F6;
  34.  
  35. { read }
  36.    HDC_STATUS  : Word = $01F7;
  37.    HDC_ALTSTA  = $03F6;
  38.  
  39. { write }
  40.    HDC_COMMAND = $01F7;
  41.    HDC_FIXED   = $03F6;
  42.  
  43. { commands }
  44.    HDC_COMMAND_RESTORE = $10;
  45.    HDC_COMMAND_SEEK    = $70;
  46.    HDC_COMMAND_READ    = $20;
  47.    HDC_COMMAND_WRITE   = $30;
  48.    HDC_COMMAND_FORMAT  = $50;
  49.    HDC_COMMAND_READVER = $90;
  50.    HDC_COMMAND_DIAG    = $90;
  51.    HDC_COMMAND_SETPAR  = $91;
  52.    HDC_COMMAND_WRSTACK = $E8;
  53.    HDC_COMMAND_RDSTACK = $E4;
  54.    HDC_COMMAND_READPAR = $EC;
  55.    HDC_COMMAND_POWER   = $E0;
  56.  
  57.    HDC_FIXED_IRQ       = $02;
  58.    HDC_FIXED_RESET     = $04;
  59.  
  60.    HDC_STATUS_ERROR    = $01;
  61.    HDC_STATUS_INDEX    = $02;
  62.    HDC_STATUS_ECC      = $04;
  63.    HDC_STATUS_DRQ      = $08;
  64.    HDC_STATUS_COMPLETE = $10;
  65.    HDC_STATUS_WRFAULT  = $20;
  66.    HDC_STATUS_READY    = $40;
  67.    HDC_STATUS_BUSY     = $80;
  68.  
  69. type
  70.    TIdeTypes = record
  71.       Cylinders,
  72.       Heads,
  73.       Sectors: Word;
  74.       Name: String[38];
  75.    end;
  76.  
  77.    PIdeInfo = ^TIdeInfo;
  78.    TIdeInfo = record
  79.       genconf,
  80.       fixcyls,
  81.       remcyls,
  82.       heads,
  83.       bytetrack,                     { bytes per track }
  84.       bytesector,                    { bytes per sector }
  85.       sectors,                             { sectors per track }
  86.       byteisg,                             { bytes intesector gap }
  87.       byteplo,                             { bytes in sync }
  88.       worduniq: Word;                { words unique status }
  89.       serial: array[1..20] of Char;
  90.       contype,                       { controller type }
  91.       bufsiz,                             { buffer size in 512 byte blocks }
  92.       byteecc: Word;                     { ECC bytes trasferred in read/write long }
  93.       firmware: array[1..8] of Char; { firmware revision }
  94.       model: array[1..40] of Char;   { model ID }
  95.       secsint,                             { number of sectors transferred per
  96. interrupt }      dblword,                             { double word transfer flag }
  97.       writepro: Word;                { write protect }
  98.    end;
  99.  
  100. const
  101.    IdesInDataBase = 17;
  102.  
  103.    IdeTypes: array[1..IdesInDataBase] of TIdeTypes =
  104.    ((Cylinders:667;  Heads:4;  Sectors:33; Name:'Fujitsu M2611T (42.9 MB)'),
  105.     (Cylinders:667;  Heads:8;  Sectors:33; Name:'Fujitsu M2612T (85.9 MB)'),
  106.     (Cylinders:667;  Heads:12; Sectors:33; Name:'Fujitsu M2613T (128.9 MB)'),
  107.     (Cylinders:667;  Heads:16; Sectors:33; Name:'Fujitsu M2614T (171.9 MB)'),
  108.     (Cylinders:782;  Heads:2;  Sectors:27; Name:'Western Digital WD93024-A (20.6 MB)'),
  109.     (Cylinders:782;  Heads:4;  Sectors:27; Name:'Western Digital WD93044-A (41.2 MB)'),
  110.     (Cylinders:845;  Heads:3;  Sectors:35; Name:'Toshiba MK232FC (45.4 MB'),
  111.     (Cylinders:845;  Heads:7;  Sectors:35; Name:'Toshiba MK234FC (106 MB'),
  112.     (Cylinders:965;  Heads:5;  Sectors:17; Name:'Quantum ProDrive 40AT (40 MB)'),
  113.     (Cylinders:965;  Heads:10; Sectors:17; Name:'Quantum ProDrive 80AT (80 MB)'),
  114.     (Cylinders:1050; Heads:2;  Sectors:40; Name:'Teac SD-340 (41 MB)'),
  115.     (Cylinders:776;  Heads:8;  Sectors:33; Name:'Conner CP-3104 (100 MB)'),
  116.     (Cylinders:745;  Heads:4;  Sectors:28; Name:'Priam 3804M (40.7 MB)'),
  117.     (Cylinders:980;  Heads:10; Sectors:17; Name:'Western Digitial Caviar AC280 (81 MB)'),
  118.     (Cylinders:560;  Heads:6;  Sectors:26; Name:'Seagate ST157A (42 MB)'),
  119.     (Cylinders:732;  Heads:8;  Sectors:35; Name:'ALPS ELECTRIC Co.,LTD. DR311C (102 MB)'),
  120.     (Cylinders:0;    Heads:0;  Sectors:0;  Name:''));
  121.  
  122. type
  123.    parray = ^tarray;
  124.    tarray = array[1..256] of Word;
  125.  
  126. var
  127.    secbuf: parray;
  128.    drive: Byte;
  129.    drv: String[1];
  130.  
  131. procedure printinfo;
  132.  
  133. var
  134.    id: TIdeInfo;
  135.    capacity: Word;
  136.    types: String;
  137.    i: Integer;
  138.  
  139.    function zo(const value: Byte): String;
  140.    begin
  141.       if Boolean(value) then
  142.          zo := ''
  143.       else
  144.          zo := 'not';
  145.    end;
  146.  
  147.    function ToStr(value: LongInt): String;
  148.    var
  149.       S: String;
  150.    begin
  151.       Str(value, S);
  152.       ToStr := S;
  153.    end;
  154.  
  155.    function ConvertHex(Value: Word): String;
  156.  
  157.    const
  158.       hexTable: array[0..15] of Char = '0123456789ABCDEF';
  159.  
  160.    begin
  161.       ConvertHex := hexTable[Hi(Value) shr 4] + hexTable[Hi(Value) and $f] +
  162.                     hexTable[Lo(Value) shr 4] + hexTable[Lo(Value) and $f];
  163.    end;
  164.  
  165.    procedure SwapBytes(var Source, Dest; Len: Byte); assembler;
  166.    asm
  167.        push  ds
  168.  
  169.        lds   si, Source
  170.        les   di, Dest
  171.        mov   cl, len
  172.        xor   ch, ch
  173.  
  174.    @1: mov   ax, ds:[si]
  175.        xchg  ah, al
  176.        mov   es:[di], ax
  177.        inc   si
  178.        inc   si
  179.        inc   di
  180.        inc   di
  181.        loop  @1
  182.  
  183.        pop    ds
  184.    end;
  185.  
  186. begin
  187.    id := PIdeInfo(secbuf)^;
  188.  
  189.    { get disk type by characteristics }
  190.    i := 1;
  191.    while IdeTypes[i].Cylinders <> 0 do
  192.       Begin
  193.          if (IdeTypes[i].cylinders = id.fixcyls) and
  194.             (IdeTypes[i].heads = id.heads) and
  195.             (IdeTypes[i].sectors = id.sectors) then
  196.             Begin
  197.                types := IdeTypes[i].name;
  198.                break;
  199.             end;
  200.          inc(i);
  201.       end;
  202.  
  203.    { unknown disk }
  204.    if (IdeTypes[i].cylinders = 0) then
  205.       Begin
  206.          types := 'Unknown ';
  207.  
  208.          { calculate capacity in MB }
  209.          capacity := (LongInt(id.fixcyls) * id.heads * id.sectors) div 2048;
  210.          types := types + ToStr(capacity);
  211.          types := types + ' Mbytes';
  212.       end;
  213.  
  214.    { swap bytes in ASCII fields except for WD disks }
  215.  
  216.    if (i <> 4) and (i <> 5) then
  217.       Begin
  218.          SwapBytes(id.serial, id.serial, 10);
  219.          SwapBytes(id.firmware, id.firmware, 4);
  220.          SwapBytes(id.model, id.model, 20);
  221.       end;
  222.  
  223.    WriteLn('Informations for drive ', drive-2, ', ', types);
  224.    WriteLn('Drive ID ', ConvertHex(id.genconf));
  225.    WriteLn(id.fixcyls, ' fixed cylinders, ', id.remcyls, ' removables');
  226.    WriteLn(id.heads, ' heads, ', id.sectors, ' sectors');
  227.    WriteLn('Serial number: ', id.serial);
  228.    WriteLn('Controller firmware: ', id.firmware);
  229.    WriteLn('Controller model: ', id.model);
  230.    WriteLn(id.bytetrack, ' bytes per track, ', id.bytesector, ' per sector');
  231.    WriteLn(id.byteisg, ' bytes of intersector gap, ', id.byteplo, ' of sync');
  232.    WriteLn('Controller type ', id.contype, ', buffer ', id.bufsiz div 2, 'KBytes');
  233.    WriteLn(id.byteecc, ' bytes of ECC, ', id.secsint, ' sector(s) transferred per interrupt');
  234.    WriteLn('Double word transfer ', zo(id.dblword),' allowed, ', zo(id.writepro), 'write protected.');
  235. end;
  236.  
  237. procedure readsect; assembler;
  238. asm
  239. { poll DRQ }
  240. @1: mov   dx, HDC_STATUS
  241.     in    al, dx
  242.     and   al, HDC_STATUS_BUSY
  243.     or    al, al
  244.     jne   @1
  245.  
  246. { read up sector }
  247.     mov   cx, 256
  248.     mov   dx, HDC_DATA
  249.     les   di, secbuf
  250. @2: in    ax, dx
  251.     mov   es:[di], ax
  252.     inc   di
  253.     inc   di
  254.     loop  @2
  255. end;
  256.  
  257. function DriveValid(Drive: Char; var Drv: Byte): Boolean; assembler;
  258. asm
  259.     mov   ah, 19h      { Save the current drive in BL }
  260.     int   21h
  261.     mov   bl, al
  262.     mov   dl, Drive    { Select the given drive }
  263.     sub   dl, 'A'
  264.     les   di, DRV
  265.     mov   es:[di], dl
  266.     mov   ah, 0Eh
  267.     int   21h
  268.     mov   ah, 19h      { Retrieve what DOS thinks is current }
  269.     int   21h
  270.     mov   cx, 0        { Assume false }
  271.     cmp   al, dl       { Is the current drive the given drive? }
  272.     jne   @1
  273.     mov   cx, 1        { It is, so the drive is valid }
  274.     mov   dl, bl       { Restore the old drive }
  275.     mov   ah, 0eh
  276.     int   21h
  277. @1: xchg  ax, cx       { Put the return value into AX }
  278. end;
  279.  
  280. function CurDisk: Byte; assembler;
  281. { Returns current drive }
  282. asm
  283.     mov   ah, 19h
  284.     int   21h
  285. end;
  286.  
  287. begin
  288.    if ParamCount > 0 then
  289.       Begin
  290.          drv := ParamStr(1);
  291.          drv[1] := UpCase(drv[1]);
  292.          if not DriveValid(drv[1], Drive) or not (drv[1] in ['C'..'Z']) then
  293.             Begin
  294.                WriteLn('There isn''t such drive or drive invalid!');
  295.                Halt(1);
  296.             end;
  297.       end
  298.    else
  299.       drive := CurDisk;
  300.  
  301.    { disable interrupt from drive }
  302.    Port[HDC_FIXED] := HDC_FIXED_IRQ;
  303.  
  304.    { set up task file parameter }
  305.    Port[HDC_SDH] := $A0 + (drive shl 4);
  306.  
  307.    { issue read parameters }
  308.    Port[HDC_COMMAND] := HDC_COMMAND_READPAR;
  309.  
  310.    GetMem(secbuf, SizeOf(secbuf));
  311.  
  312.    { read up sector }
  313.    readsect;
  314.  
  315.    { print out info }
  316.    printinfo;
  317.  
  318.    FreeMem(secbuf, SizeOf(secbuf));
  319. end.
  320.